package org.hs.phd.common.framesource;

import static com.googlecode.javacv.cpp.opencv_core.cvCopy;

import java.awt.Rectangle;

import com.googlecode.javacv.cpp.opencv_core;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.cpp.opencv_highgui;

public class FolderFrameSource implements FrameSource{
	
	
	private final String filePathPrefix;
	private final String suffix;
	private int currentFrameNo;
	private Rectangle roi;
	private final int startFrameNo;
	private FlipType flipType;

	public FolderFrameSource( String filePathPrefix, String suffix, int startFrameNo){
		this.filePathPrefix = filePathPrefix;
		this.suffix = suffix;
		this.startFrameNo = startFrameNo;
		this.flipType = FlipType.NONE;
		currentFrameNo = startFrameNo;
		
	}
	
	@Override
	public ImageSequenceFrame loadNextFrame(){
		currentFrameNo++;
		return loadCurrentFrame();
	}

	@Override
	public ImageSequenceFrame loadPreviousFrame() {
		currentFrameNo--;
		return loadCurrentFrame();
	}


	private ImageSequenceFrame loadCurrentFrame() {
		
		String currentImageFileName = filePathPrefix + currentFrameNo + suffix;
		
		IplImage readImage = opencv_highgui.cvLoadImage(currentImageFileName);

		if( readImage == null ) throw new EndOfFrameSourceException( currentImageFileName + "not found!" );
		
		readImage = cropImage(readImage);
		
//		IplImage result2 = opencv_core.cvCreateImage(opencv_core.cvSize(roi.width/2, roi.height/2), result1.depth(), result1.nChannels());
//		opencv_imgproc.cvPyrDown(result1, result2, opencv_imgproc.CV_GAUSSIAN_5x5);
//		opencv_core.cvReleaseImage(result1);

		flipImage(readImage);
		
		return new DefaultImageSequenceFrameImpl( currentFrameNo, readImage);
	}

	private IplImage cropImage(IplImage readImage) {
		if( roi != null ){
			opencv_core.cvSetImageROI(readImage, opencv_core.cvRect(roi.x, roi.y, roi.width, roi.height));
			IplImage result1 = opencv_core.cvCreateImage(opencv_core.cvSize(roi.width, roi.height), readImage.depth(), readImage.nChannels());
			cvCopy(readImage, result1);
			opencv_core.cvReleaseImage(readImage);
			readImage = result1;
		}
		return readImage;
	}

	private void flipImage(IplImage result1) {
		if( flipType != FlipType.NONE ){	
			int flipCode = flipType == FlipType.FLIP_AROUND_BOTH_AXES ? -1 : (flipType == FlipType.FLIP_AROUND_X_AXIS ? 0 : 1);
			opencv_core.cvFlip(result1, null, flipCode);
		}
	}

	@Override
	public void setROI(Rectangle roi) {
		this.roi = roi;
	}

	@Override
	public FramePlayer createPlayer(int interFrameMilliseconds,
			FrameProcessor frameProcessor) {
		return new DefaultFramePlayer(this, interFrameMilliseconds, frameProcessor);
	}

	@Override
	public void reset() {
		currentFrameNo = startFrameNo;
	}

	@Override
	public void setFlip(FlipType flipType) {
		this.flipType = flipType;
	}

}
